﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Network.Tcp;

public abstract class TcpServerBase : TcpBase
{
    public TcpServerBase(string name) : base(name)
    {
    }
    public void SetBindAddress(IPEndPoint bindIPEndPoint)
    {
        BindIPEndPoint = bindIPEndPoint;
        ListenSocket = new Socket(BindIPEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        Console.WriteLine($"ListenSocket:{ListenSocket}, Blocking:{ListenSocket.Blocking}");
        ListenSocket.Blocking = false;
        Console.WriteLine($"ListenSocket:{ListenSocket}, Blocking:{ListenSocket.Blocking}");

        ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
    }

    public override bool Init()
    {
        if (ListenSocket == null || BindIPEndPoint == null)
            return false;
        ListenSocket.Bind(BindIPEndPoint);
        try
        {
            ListenSocket.Listen();
        }
        catch (SocketException ex)
        {
            Console.WriteLine($"Listen Error:{ex.Message}");
            ListenSocket.Dispose();
            return false;
        }
        return true;
    }

    protected void DoAccept()
    {
        if (ListenSocket == null)
            return;
        try
        {
            Socket socket = ListenSocket.Accept();
            ConnectData connectData = new ConnectData();
            connectData.Socket = socket;
            connectData.SessionID = TcpUtility.GetSessionID();
            connectData.IPEndPoint = socket.RemoteEndPoint as IPEndPoint;
            AddConnect(connectData);
        }
        catch (SocketException ex)
        {
            Console.WriteLine($"Accept Failed. {ex.Message}");
        }
    }

    public override void ThreadExit()
    {
        base.ThreadExit();
        ListenSocket?.Close();
    }

    protected Socket? ListenSocket;
    protected IPEndPoint? BindIPEndPoint;
}
